#include <stdio.h>
#include <windows.h>
#include <malloc.h>

#define TRUE 1
#define FALSE 0

	#define LIST_INIT_SIZE 100
	#define LIST_INCREMENT 10

	#define ELEM_INITIAL 0

	typedef int elemType ;
	typedef struct{
		elemType* elem;
		int length;
		int listSize;	
	} SqList;

	int _error(char* msg)
	{
		printf();
	}

	int InitList(SqList* L)
	{
		L->elem = (elemType*) malloc(LIST_INIT_SIZE * sizeof elemType);
		if (L->elem == NULL)
		{
			printf("Application of memory failure.\n");
			system("pause");
			exit(FALSE);
		}

		L->length = 0;
		L->listSize = LIST_INIT_SIZE;

		return TRUE;
	}

	int ListNone(SqList L)
	{
		if (L.listSize == 0 || L.elem == NULL) return TRUE;
		return FALSE;
	}

	int DestoryList(SqList* L)
	{
		free(L->elem);
		L->elem = NULL;
		L->length = 0;
		L->listSize = 0;

		return TRUE;
	}

	int ListLength(SqList L)
	{
		if (L.length < 0 || L.length > L.listSize || ListNone(L)) 
		{
			printf("Structure internal error.\n");
			system("pause");
			exit(FALSE);
		}
		else return L.length;
	}

	int ClearList(SqList* L)
	{
		ListLength(*L);

		while(L->length)
		{
			L->elem[--L->length] = ELEM_INITIAL;
		}

		return TRUE;
	}

	int ListEmpty(SqList L)
	{
		return ListLength(L) == 0 ? TRUE : FALSE;
	}

	int GetElem(SqList L, int i, elemType* e)
	{
		int len = ListLength(L);

		if (i <= 0 || i > len || ListEmpty(L))
		{
			printf("The second parameter 'position' bounds, or list is empty.\n");
			system("pause");
			exit(FALSE);
		}

		*e = L.elem[i-1];
		
		return TRUE;
	}

	int _equl(elemType m,elemType n)
	{
		return m == n ? TRUE : FALSE;
	}

	int LocateElem(SqList L, elemType e, int (*compare)(elemType, elemType) = _equl)
	{
		int len = ListLength(L);
		elemType temp;

		while(len--)
		{
			GetElem(L, len, &temp);
			if (compare(temp, e)) return len;
		}

		return FALSE;
	}

	int PriorElem(SqList L, elemType curE, elemType* preE)
	{
		int pos = LocateElem(L, curE);
		if (pos == 0 || pos == 1)
		{
			printf("Element no found in list, or the element you given is first in the list.\n");
			system("pause");
			exit(FALSE);
		}
		else GetElem(L, pos-1, preE);

		return TRUE;
	}

	int NextElem(SqList L, elemType curE, elemType* nextE)
	{
		int pos = LocateElem(L, curE);
		if (pos == 0 || pos == ListLength(L))
		{
			printf("Element no found in list, or the element you given is the last in the list.\n");
			system("pause");
			exit(FALSE);
		}
		else GetElem(L, pos+1, nextE);

		return TRUE;
	}

	int ListInsert(SqList* L, int i, elemType e)
	{
		int len = ListLength(*L);
		elemType* listTemp;

		if (i < 1)
		{
			printf("The second parameter 'position' bounds.\n");
			system("pause");
			exit(FALSE);
		}

		if (len >= L->listSize) 
		{
			listTemp = (elemType*)realloc(L->elem, L->listSize + LIST_INCREMENT);

			if (listTemp != NULL)
			{
				free(L->elem);
				L->elem = listTemp;
				L->listSize += LIST_INCREMENT;
			}
			else
			{
				printf("Get new memory address failure.\n");
				system("pause");
				exit(FALSE);
			}
		}

		if (i > len || ListEmpty(*L)) L->elem[len] = e;
		else
		{
			do
			{
				L->elem[len] = L->elem[len-1];
			}while(len-- != i);

			L->elem[len] = e;
		}		
		L->length++;

		return TRUE;
	}

	int ListDelete(SqList *L, int i, elemType* e)
	{
		int len = ListLength(*L);
		if (ListEmpty(*L) || i < 1 || i > len)
		{
			printf("The second parameter 'position' bounds, or list is empty.\n");
			system("pause");
			exit(FALSE);
		}

		GetElem(*L, i, e);

		while(i++ != len)
		{
			L->elem[i-2] = L->elem[i-1];
		}

		L->elem[len-1] = ELEM_INITIAL;
		L->length--;

		return TRUE;
	}

	int _show(elemType* e)
	{
		printf("value:\t%d\n",*e);
		return 0;
	}

	int ListTraverse(SqList L, int (*visit)(elemType* e) = _show)
	{
		int len = ListLength(L);
		while(len--)
		{
			visit(&(L.elem[len]));
		}

		return 0;
	}

	//Assuming every SqList has ran InitList function before use;
	//The use of array-subscirpt are follow the normal usage, from the beginning of 1
	//The internal calculations from the beginning of 0

	int main()
	{
		SqList examL;
		elemType examE;
		InitList(&examL);

		if (ListEmpty(examL)) printf("Now, list is empty, and we will insert data into it!\n");

		DestoryList(&examL);
		InitList(&examL);

		ListInsert(&examL, 9, 11);
		ListInsert(&examL, 9, 12);
		ListInsert(&examL, 9, 13);
		ListInsert(&examL, 9, 14);
		ListInsert(&examL, 9, 15);
		ListInsert(&examL, 9, 16);

		ListTraverse(examL);
		printf("\nTotal ength:%d\n\n",ListLength(examL));

		printf("next, clear the list.See it again.\n");
		ClearList(&examL);

		ListTraverse(examL);
		printf("\nTotal ength:%d\n\n",ListLength(examL));

		printf("insert data again\n");
		ListInsert(&examL, 9, 11);
		ListInsert(&examL, 9, 12);
		ListInsert(&examL, 9, 13);
		ListInsert(&examL, 9, 14);
		ListInsert(&examL, 9, 15);
		ListInsert(&examL, 9, 16);

		ListTraverse(examL);
		printf("\nTotal ength:%d\n\n",ListLength(examL));

		GetElem(examL, 3, &examE);
		printf("elem 3 value:%d\n",examE);

		printf("Show where '12' is:%d\n",LocateElem(examL, 12));
		
		NextElem(examL, 12, &examE);
		printf("Show element next '12':%d\n",examE);

		PriorElem(examL, 12, &examE);
		printf("Show element before '12':%d\n",examE);

		ListInsert(&examL, 3, 10);
		printf("Put the '10' as third element, show new list:\n");
		ListTraverse(examL);
		printf("\nTotal ength:%d\n\n",ListLength(examL));

		ListDelete(&examL, 3, &examE);
		printf("Delete value '10' now, who is delete:%d\nshow again:\n",examE);
		ListTraverse(examL);
		printf("\nTotal ength:%d\n\n",ListLength(examL));

		system("pause");
		return 0;
	}